﻿using System.Collections.Generic;
using System;
using BCService.Utils;
using BCCommon;
using BCCommon.TMS.Driver;
using BCEntity.Common.EntityNameConst;
using BCDto.TMS.LearnTrain.VehicleTrainingScheduleRecord;
using BCDto.TMS.LearnTrain.PendingLearningVehicle;
using BCData.TMS.LearningTrain;
using BCDto.Sim.Admin.Admin;
using BCData.TMS.Driver;
using BCEntity.TMS.LearningTrain.DriverAbsenteeismRecord;
using System.Linq;
using BCData.Common.Dictionary;
using BCEntity.TMS.LearningTrain.AllowedExaminationRecord;
using BCDto.TMS.LearnTrain;
using BCDto.TMS.LearnTrain.LearnTrainStatistics;
using BCCommon.TMS.LearnTrain;
using BCDto.TMS.LearnTrain.VehicleTrainingScheduleRecord.TrainingScheduleRecordRequest;

namespace BCService.TMS.LearningTrain
{
    public class PendingLearningVehicleService : IPendingLearningVehicleService
    {
        #region var
        private readonly IDatabaseContext databaseContext;
        private readonly IPendingLearningVehicleData pendingLearningVehicleData;
        private readonly IVehicleTrainingScheduleRecordData vehicleTrainingScheduleRecordData;
        private readonly IRedisService redisService;
        private readonly IDriverData driverData;
        private readonly IDriverAbsenteeismRecordData driverAbsenteeismRecordData;
        private readonly IDictionaryReferenceData dictionaryReferenceData;
        private readonly IAllowedExaminationRecordData allowedExaminationRecordData;
        private readonly string keyPendingLearningVehicleEntity = string.Format("{0}", EntityNameConst.PendingLearningVehicleEntity);
        private readonly string keyVehicleTrainingScheduleRecordEntity = string.Format("{0}", EntityNameConst.VehicleTrainingScheduleRecordEntity);
        private readonly string keyLearnTrainHistoryRecord = string.Format("{0}", EntityNameConst.LearnTrainHistoryRecordEntity);
        private readonly string keyExaminationStatisticsEntity = string.Format("{0}", EntityNameConst.ExaminationStatisticsEntity);
        private readonly string keyLearnTrainExaminationDriverEntity = string.Format("{0}", EntityNameConst.LearnTrainExaminationDriverEntity);
        
        #endregion

        #region 构造函数
        public PendingLearningVehicleService(IPendingLearningVehicleData pendingLearningVehicleData,
            IDatabaseContext databaseContext,
            IRedisService redisService,
            IVehicleTrainingScheduleRecordData vehicleTrainingScheduleRecordData,
            IDriverData driverData,
            IDriverAbsenteeismRecordData driverAbsenteeismRecordData,
            IDictionaryReferenceData dictionaryReferenceData, 
            IAllowedExaminationRecordData allowedExaminationRecordData)
        {
            this.pendingLearningVehicleData = pendingLearningVehicleData;
            this.databaseContext = databaseContext;
            this.redisService = redisService;
            this.vehicleTrainingScheduleRecordData = vehicleTrainingScheduleRecordData;
            this.driverData = driverData;
            this.driverAbsenteeismRecordData = driverAbsenteeismRecordData;
            this.dictionaryReferenceData = dictionaryReferenceData;
            this.allowedExaminationRecordData = allowedExaminationRecordData;
        }
        #endregion

        public PendingLearningVehicleDto GetPendingLearningVehicle(long driverId)
        {
            var pendingLearningVehicle = this.pendingLearningVehicleData.GetEntityByDriverId(driverId).Result;
            return pendingLearningVehicle.As<PendingLearningVehicleDto>();
        }

        public VehicleTrainingScheduleStatisticsDto GetTrainingScheduleStatistics(long vehicleTrainingScheduleRecordId)
        {
            string cacheKey = this.redisService.GetKey(keyVehicleTrainingScheduleRecordEntity, vehicleTrainingScheduleRecordId);
            var resultRedis = this.redisService.TryGet(cacheKey, () =>
            {
                var result = this.pendingLearningVehicleData.GetTrainingScheduleStatistics(vehicleTrainingScheduleRecordId).GetAwaiter().GetResult();
                return result.As<VehicleTrainingScheduleStatisticsDto>();
            }, TimeSpan.FromDays(1));
            return resultRedis;
        }

        public IEnumerable<VehicleTrainingScheduleDetailDto> GetVehicleTrainingScheduleDetail(AdminDto admin,
            long vehicleTrainingScheduleRecordId, string phone)
        {
            if (admin.AgentRecord == null)
            {
                throw new ArgumentException(" 用户验证失败,错误操作 ");
            }
            var vehicleTrainingScheduleRecordEntity = this.vehicleTrainingScheduleRecordData.GetEntityAsync(vehicleTrainingScheduleRecordId).Result;
            if (vehicleTrainingScheduleRecordEntity == null)
            {
                throw new ArgumentException(" 获取当前培训记录失败 ");
            }
            if (admin.AgentRecord.AgentRecordId != vehicleTrainingScheduleRecordEntity.AgentRecordId)
            {
                throw new ArgumentException(" 不可查看别的代理商的培训记录 ");
            }
            string cacheKey = this.redisService.GetKey(keyPendingLearningVehicleEntity, admin.AgentRecord.AgentRecordId, vehicleTrainingScheduleRecordId,
                phone);
            var resultRedis = this.redisService.TryGet(cacheKey, () =>
            {
                var list = this.pendingLearningVehicleData.GetVehicleTrainingScheduleDetail(admin.AgentRecord.AgentRecordId, vehicleTrainingScheduleRecordId,
                    phone).GetAwaiter().GetResult();
                return list.As<IEnumerable<VehicleTrainingScheduleDetailDto>>();
            }, TimeSpan.FromDays(1));
            return resultRedis;
        }

        public PageableList<PendingLearningVehicleViewDto> Query(AdminDto admin,string driverName, string vehicleNo, DriverRoleType? driverRoleType,
            bool? isTrainingScheduleRecord, DateTime? notifyStartDate, DateTime? notifyEndDate, int pageIndex, int pageSize)
        {
            if (admin.AgentRecord == null)
            {
                throw new ArgumentException(" 用户验证失败,错误操作 ");
            }
            string cacheKey = this.redisService.GetKey(keyPendingLearningVehicleEntity, admin.AgentRecord.AgentRecordId, driverName, vehicleNo, driverRoleType,
                isTrainingScheduleRecord, notifyStartDate, notifyEndDate, pageIndex, pageSize);
            var resultRedis = this.redisService.TryGet(cacheKey, () =>
            {
                var (list, count) = this.pendingLearningVehicleData.Query(admin.AgentRecord.AgentRecordId, driverName, vehicleNo, driverRoleType,
                isTrainingScheduleRecord, notifyStartDate, notifyEndDate, pageIndex, pageSize).GetAwaiter().GetResult();
                var tempList = list.As<IEnumerable<PendingLearningVehicleViewDto>>();
                foreach (var item in tempList)
                {
                    //未分配 ||已缺考 || 分配了但是结束时间过期 
                    if (!item.VehicleTrainingScheduleRecordId.HasValue || item.IsAbsenteeism || (item.TrainingEndDate.HasValue && !(item.TrainingEndDate >= DateTime.Now.Date)))
                    {
                        item.IsAllowOperate = true;
                    }
                }
                return new PageableList<PendingLearningVehicleViewDto>()
                {
                    Items = tempList,
                    Count = count,
                    ServerTime = DateTime.Now,
                    PageIndex = pageIndex,
                    PageSize = pageSize,
                };
            }, TimeSpan.FromDays(1));
            return resultRedis;
        }


        public bool MissExtension(AdminDto admin, long vehicleTrainingScheduleRecordId, long pendingLearningVehicleId)
        {
            if (admin.AgentRecord == null)
            {
                throw new ArgumentException(" 用户认证失败,错误操作 ");
            }
            var record = this.vehicleTrainingScheduleRecordData.GetEntityAsync(vehicleTrainingScheduleRecordId).GetAwaiter().GetResult();
            if (record == null)
            {
                throw new ArgumentException("培训计划不存在");
            }
            var pendingLearningVehicle = this.pendingLearningVehicleData.GetEntityAsync(pendingLearningVehicleId).GetAwaiter().GetResult();
            if (pendingLearningVehicle == null)
            {
                throw new ArgumentException("待培训车辆信息不存在。");
            }
            if (!pendingLearningVehicle.VehicleTrainingScheduleRecordId.HasValue)
            {
                throw new ArgumentException("司机还未安排培训，请先去安排培训。");
            }
            if (pendingLearningVehicle.IsAbsenteeism)
            {
                throw new ArgumentException("已设置过缺席，不能重复设置。");
            }
            var driver = this.driverData.GetDriverByIdAsync(pendingLearningVehicle.DriverId).Result;
            if (driver == null)
            {
                throw new ArgumentException("司机信息不存在。");
            }
            if (driver.IsLearnTrainPassed)
            {
                throw new ArgumentException("该司机已通过考试，不可设置缺席。");
            }
            
            pendingLearningVehicle.IsAbsenteeism = true;
            pendingLearningVehicle.IsOnceAbsenteeism = true;
            this.databaseContext.BeginTransaction();
            this.driverData.LearnTrainSignAsync(driver.DriverId, false).GetAwaiter().GetResult();
            var result = this.pendingLearningVehicleData.UpdateAsync(pendingLearningVehicle).GetAwaiter().GetResult();
            if (result != null)
            {
                var driverAbsenteeismRecordEntity = new DriverAbsenteeismRecordEntity()
                {
                    DriverAbsenteeismRecordCode = Guid.NewGuid().ToString(),
                    DriverId = pendingLearningVehicle.DriverId,
                    PendingLearningVehicleId = pendingLearningVehicleId,
                    VehicleTrainingScheduleRecordId = vehicleTrainingScheduleRecordId,
                    Mark = "司机缺考",
                    CreateTime = DateTime.Now,
                    CreateAdminId = admin.AdminId,
                    CreateAdminName = admin.FullName,
                };
                this.driverAbsenteeismRecordData.InsertAsync(driverAbsenteeismRecordEntity).GetAwaiter().GetResult();
            }
            this.databaseContext.Commit();
            this.redisService.DeleteMultipleKey(keyPendingLearningVehicleEntity, false);
            return result != null;
        }

        public bool AllowJoinExam(AdminDto admin, long vehicleTrainingScheduleRecordId, VehicleTrainingScheduleRecordPutDto putDto)
        {
            if (admin.AgentRecord == null)
            {
                throw new ArgumentException(" 用户认证失败,错误操作 ");
            }
            if (!putDto.PendingLearningVehicleIds.Any())
            {
                throw new ArgumentException("暂无待培训人员");
            }
            var limitDuration = dictionaryReferenceData.GetEntityAsync("Test_A_LimitDuration").GetAwaiter().GetResult();
            if (limitDuration == null)
            {
                throw new ArgumentException("尚未设置考试限制时长。");
            }
            var vehicleTrainingScheduleRecord = this.vehicleTrainingScheduleRecordData.GetEntityAsync(vehicleTrainingScheduleRecordId).Result;
            if (vehicleTrainingScheduleRecord == null)
            {
                throw new ArgumentException(" 获取培训安排记录信息失败 ");
            }
            if (DateTime.Compare(DateTime.Now.Date, vehicleTrainingScheduleRecord.TrainingStartDate.Date) < 0 || DateTime.Compare(DateTime.Now.Date, vehicleTrainingScheduleRecord.TrainingEndDate.Date) > 0)
            {
                throw new ArgumentException("当前时间不允许安排考试。");
            }
            var listDriver = pendingLearningVehicleData.GetListByIdsAsync(putDto.PendingLearningVehicleIds).GetAwaiter().GetResult();
            if (listDriver.Any())
            {
                this.databaseContext.BeginTransaction();
                var result = this.pendingLearningVehicleData.AllowJoinExamAsync(listDriver.Select(g => g.DriverId).ToList(),
                    vehicleTrainingScheduleRecordId, Convert.ToInt32(limitDuration.ItemValue)).GetAwaiter().GetResult();
                if (!result)
                {
                    throw new ArgumentException("设置允许考试失败。");
                }
                var allowedExaminationRecordEntity = new AllowedExaminationRecordEntity()
                {
                    AllowedExaminationRecordCode = Guid.NewGuid().ToString(),
                    VehicleTrainingSchedulerecordId = vehicleTrainingScheduleRecordId,
                    LimitDuration = Convert.ToInt32(limitDuration.ItemValue),
                    CreateTime = DateTime.Now,
                    CreateAdminId = admin.AdminId,
                    CreateAdminName = admin.FullName,
                };
                this.allowedExaminationRecordData.InsertAsync(allowedExaminationRecordEntity).GetAwaiter().GetResult();
                this.databaseContext.Commit();
            }
            this.redisService.DeleteMultipleKey(keyPendingLearningVehicleEntity, false);
            return true;
        }

        #region 进入考场

        /// <summary>
        /// 考场统计
        /// </summary>
        /// <param name="vehicleTrainingScheduleRecordId">培训安排id</param>
        /// <returns></returns>
        public ExaminationStatisticsDto GetExaminationStatistics(long vehicleTrainingScheduleRecordId)
        {
            string cacheKey = this.redisService.GetKey(keyExaminationStatisticsEntity, vehicleTrainingScheduleRecordId);
            var resultRedis = this.redisService.TryGet(cacheKey, () =>
            {
                var result = this.pendingLearningVehicleData.GetExaminationStatistics(vehicleTrainingScheduleRecordId).GetAwaiter().GetResult();
                if (result == null)
                {
                    throw new ArgumentException("获取考试人数失败。");
                }
                if (string.IsNullOrWhiteSpace(result.TrainingPeriods))
                {
                    throw new ArgumentException("此次培训无培训期数，不可进入考场。");
                }
                var allPracticalLearningCountEntity = this.pendingLearningVehicleData.GetAllTrainCount().GetAwaiter().GetResult();
                var resultExaminationTime = this.pendingLearningVehicleData.GetLearnTrainAllowedExaminationRecordEntity(vehicleTrainingScheduleRecordId).GetAwaiter().GetResult();
                if (resultExaminationTime == null)
                {
                    throw new ArgumentException("获取允许考试时间失败。");
                }
                var examinationEndTime = resultExaminationTime.CreateTime.AddMinutes(Convert.ToDouble(resultExaminationTime.LimitDuration));//考试结束时间
                return result.TransformTo<ExaminationStatisticsDto>(onAfter: (_, dest) =>
                {
                    dest.AllowedExaminationTime = resultExaminationTime.CreateTime;//允许考试时间
                    dest.AllPracticalLearningCount = allPracticalLearningCountEntity?.AllPracticalLearningCount ?? 0;//累计培训人数
                    dest.LimitDuration = resultExaminationTime.LimitDuration;//考试时长
                    dest.EndExaminationTime = examinationEndTime;//考试结束时间
                });
            }, TimeSpan.FromDays(1));
            return resultRedis;
            

        }
        /// <summary>
        /// 获取考试通过和未通过司机信息
        /// </summary>
        /// <param name="vehicleTrainingScheduleRecordId">考试安排记录id</param>
        /// <param name="isLearnTrainPassed">是否考试通过</param>
        /// <returns></returns>
        public IEnumerable<LearnTrainExaminationDriverDto> GetExaminationDriverInfo(long vehicleTrainingScheduleRecordId, bool isLearnTrainPassed)
        {
            string cacheKey = this.redisService.GetKey(keyLearnTrainExaminationDriverEntity, vehicleTrainingScheduleRecordId, isLearnTrainPassed);
            var resultRedis = this.redisService.TryGet(cacheKey, () =>
            {
                var result = this.pendingLearningVehicleData.GetExaminationDriverInfo(vehicleTrainingScheduleRecordId, isLearnTrainPassed).GetAwaiter().GetResult().ToList();
                foreach (var item in result)
                {
                    item.IsMakeUp = item.TrainExamFailedTimes > 0;//是否补考
                    item.ExaminationDruation = (item.SubmitExaminationTime - item.AllowedExaminationTime).Minutes < 0 ? 0 : (item.SubmitExaminationTime - item.AllowedExaminationTime).Minutes;//考试时长
                }
                if (isLearnTrainPassed == false)
                {
                    var NoExaminationHaving = this.pendingLearningVehicleData.GetNoExaminationHaving(vehicleTrainingScheduleRecordId).GetAwaiter().GetResult();
                    if (NoExaminationHaving.Any())
                    {
                        result.AddRange(NoExaminationHaving);
                    }
                }
                return result.As<IEnumerable<LearnTrainExaminationDriverDto>>();
            }, TimeSpan.FromDays(1));
            return resultRedis;
        }

        /// <summary>
        /// 考试中司机信息
        /// </summary>
        /// <param name="vehicleTrainingScheduleRecordId">考试安排记录id</param>
        /// <returns></returns>
        public IEnumerable<LearnTrainExaminationDriverDto> GetExaminationHaving(long vehicleTrainingScheduleRecordId)
        {
            string cacheKey = this.redisService.GetKey(keyLearnTrainExaminationDriverEntity, vehicleTrainingScheduleRecordId);
            var resultRedis = this.redisService.TryGet(cacheKey, () =>
            {
                var result = this.pendingLearningVehicleData.GetExaminationHaving(vehicleTrainingScheduleRecordId).GetAwaiter().GetResult();
                if (result == null) return null;
                result = result.Where(p => (p.AllowedExaminationTime <= DateTime.Now && DateTime.Now < p.AllowedExaminationTime.AddMinutes(p.LimitDuration)) || p.TrainExamFailedTimes == 0).ToList();
                foreach (var item in result)
                {
                    item.IsMakeUp = item.TrainExamFailedTimes > 0;//是否补考
                    item.SubmitExaminationTime = item.AllowedExaminationTime.AddMinutes(item.LimitDuration);
                }
                return result.As<IEnumerable<LearnTrainExaminationDriverDto>>();
            }, TimeSpan.FromDays(1));
            return resultRedis;
        }
        #endregion

        #region 统计

        public LearnTrainDto GetLearningDriverCount(long? agentRecordId, DateTime? datetime,long? trainingSiteConfigId)
        {
            LearnTrainDto learnTrainDto = new LearnTrainDto();
            //就是本次的数据与上次数据的差值，然后比上次数据的值。
            #region 本月上月应安排培训人数统计
            var tempEntitiesPendingLearningDriver = this.pendingLearningVehicleData.GetLearningDriverCount(agentRecordId,
                datetime, LearnTrainEnum.PendingLearning, trainingSiteConfigId).GetAwaiter().GetResult();
            learnTrainDto.PendingLearningDriverDto = new PendingLearningDriverDto
            {
                PendingLearningDriverCount = tempEntitiesPendingLearningDriver.DriverCount,
                MonthPendingLearningDriverCount = tempEntitiesPendingLearningDriver.MonthDriverCount
            };
            Compare.MonthOnMonth(Convert.ToDecimal(learnTrainDto.PendingLearningDriverDto.PendingLearningDriverCount), 
                Convert.ToDecimal(learnTrainDto.PendingLearningDriverDto.MonthPendingLearningDriverCount),
                out bool isPendingLearningDriverIncrease, out string increasePendingLearningDriverRate);
            learnTrainDto.PendingLearningDriverDto.IsMonthOnMonthPendingLearningDriver = isPendingLearningDriverIncrease;
            learnTrainDto.PendingLearningDriverDto.MonthOnMonthPendingLearningDriverRate = increasePendingLearningDriverRate;
            #endregion
            #region 本月上月实际安排培训人数统计
            var tempEntitiesPracticalLearningDriver = this.pendingLearningVehicleData.GetLearningDriverCount(agentRecordId,
                datetime, LearnTrainEnum.PracticalLearning, trainingSiteConfigId).GetAwaiter().GetResult();
            learnTrainDto.PracticalLearningDriverDto = new PracticalLearningDriverDto
            {
                PracticalLearningDriverCount = tempEntitiesPracticalLearningDriver.DriverCount,
                MonthPracticalLearningDriverCount = tempEntitiesPracticalLearningDriver.MonthDriverCount
            };
            Compare.MonthOnMonth(Convert.ToDecimal(learnTrainDto.PracticalLearningDriverDto.PracticalLearningDriverCount),
                Convert.ToDecimal(learnTrainDto.PracticalLearningDriverDto.MonthPracticalLearningDriverCount), 
                out bool isPracticalLearningDriverIncrease, out string increasePracticalLearningDriverRate);
            learnTrainDto.PracticalLearningDriverDto.IsMonthOnMonthPracticalLearningDriver = isPracticalLearningDriverIncrease;
            learnTrainDto.PracticalLearningDriverDto.MonthOnMonthPracticalLearningDriverRate = increasePracticalLearningDriverRate;
            #endregion
            #region 本月上月未安排培训人数统计
            var tempEntitiesUnscheduledLearningDriver = this.pendingLearningVehicleData.GetLearningDriverCount(agentRecordId,
                datetime, LearnTrainEnum.UnscheduledLearning, trainingSiteConfigId).GetAwaiter().GetResult();
            learnTrainDto.UnscheduledLearningDto = new UnscheduledLearningDto
            {
                UnscheduledLearningDriverCount = tempEntitiesUnscheduledLearningDriver.DriverCount,
                MonthUnscheduledLearningDriverCount = tempEntitiesUnscheduledLearningDriver.MonthDriverCount
            };
            Compare.MonthOnMonth(Convert.ToDecimal(learnTrainDto.UnscheduledLearningDto.UnscheduledLearningDriverCount), 
                Convert.ToDecimal(learnTrainDto.UnscheduledLearningDto.MonthUnscheduledLearningDriverCount), 
                out bool isMonthOnMonthUnscheduledLearningDriverDriver, out string monthOnMonthUnscheduledLearningDriverRate);
            learnTrainDto.UnscheduledLearningDto.IsMonthOnMonthUnscheduledLearningDriverDriver = isMonthOnMonthUnscheduledLearningDriverDriver;
            learnTrainDto.UnscheduledLearningDto.MonthOnMonthUnscheduledLearningDriverRate = monthOnMonthUnscheduledLearningDriverRate;
            #endregion
            #region 本月上月实到安排培训人数统计
            var tempEntitiesArrivalLearningLearningDriver = this.pendingLearningVehicleData.GetLearningDriverCount(agentRecordId,
                datetime, LearnTrainEnum.ArrivalLearning, trainingSiteConfigId).GetAwaiter().GetResult();
            learnTrainDto.ArrivalLearningDto = new ArrivalLearningDto
            {
                ArrivalLearningDriverCount = tempEntitiesArrivalLearningLearningDriver.DriverCount,
                MonthArrivalLearningDriverCount = tempEntitiesArrivalLearningLearningDriver.MonthDriverCount
            };
            Compare.MonthOnMonth(Convert.ToDecimal(learnTrainDto.ArrivalLearningDto.ArrivalLearningDriverCount),
                Convert.ToDecimal(learnTrainDto.ArrivalLearningDto.MonthArrivalLearningDriverCount), 
                out bool isMonthOnMonthArrivalLearningDriverDriver, out string monthOnMonthArrivalLearningDriverRate);
            learnTrainDto.ArrivalLearningDto.IsMonthOnMonthArrivalLearningDriver = isMonthOnMonthArrivalLearningDriverDriver;
            learnTrainDto.ArrivalLearningDto.MonthOnMonthArrivalLearningDriverRate = monthOnMonthArrivalLearningDriverRate;
            #endregion
            #region 本月上月已安排未培训人数统计
            var tempEntitiesAlreadyLearningDriver = this.pendingLearningVehicleData.GetLearningDriverCount(agentRecordId,
                datetime, LearnTrainEnum.AlreadyLearning, trainingSiteConfigId).GetAwaiter().GetResult();
            learnTrainDto.AlreadyLearningDto = new AlreadyLearningDto
            {
                AlreadyLearningDriverCount = tempEntitiesAlreadyLearningDriver.DriverCount,
                MonthAlreadyLearningDriverCount = tempEntitiesAlreadyLearningDriver.MonthDriverCount
            };
            Compare.MonthOnMonth(Convert.ToDecimal(learnTrainDto.AlreadyLearningDto.AlreadyLearningDriverCount),
                Convert.ToDecimal(learnTrainDto.AlreadyLearningDto.MonthAlreadyLearningDriverCount),
                out bool isMonthOnMonthAlreadyLearningDriverDriver, out string monthOnMonthAlreadyLearningDriverRate);
            learnTrainDto.AlreadyLearningDto.IsMonthOnMonthAlreadyLearningDriver = isMonthOnMonthAlreadyLearningDriverDriver;
            learnTrainDto.AlreadyLearningDto.MonthOnMonthAlreadyLearningDriverRate = monthOnMonthAlreadyLearningDriverRate;
            #endregion

            #region 本月上月通过培训人数统计
            var tempEntitiesPassLearningDriver = this.pendingLearningVehicleData.GetLearningDriverCount(agentRecordId,
                datetime, LearnTrainEnum.PassLearning, trainingSiteConfigId).GetAwaiter().GetResult();
            learnTrainDto.PassLearningDto = new PassLearningDto
            {
                PassLearningDriverCount = tempEntitiesPassLearningDriver.DriverCount,
                MonthPassLearningDriverCount = tempEntitiesPassLearningDriver.MonthDriverCount
            };
            Compare.MonthOnMonth(Convert.ToDecimal(learnTrainDto.PassLearningDto.PassLearningDriverCount),
                Convert.ToDecimal(learnTrainDto.PassLearningDto.MonthPassLearningDriverCount), 
                out bool isMonthOnMonthPassLearningDriver, out string monthOnMonthPassLearningDriverRate);
            learnTrainDto.PassLearningDto.IsMonthOnMonthPassLearningDriver = isMonthOnMonthPassLearningDriver;
            learnTrainDto.PassLearningDto.MonthOnMonthPassLearningDriverRate = monthOnMonthPassLearningDriverRate;
            learnTrainDto.PassLearningDto.PassLearningDriverRate = Compare.GetRate(learnTrainDto.PassLearningDto.PassLearningDriverCount,
                learnTrainDto.PracticalLearningDriverDto.PracticalLearningDriverCount);
            #endregion
            return learnTrainDto;
        }


        public LearnTrainAnalysisDto GetTrainSeheduleMonthAnalysis(AdminDto admin, DateTime? date)
        {
            if (admin.AgentRecord == null)
            {
                throw new ArgumentException(" 用户认证失败,错误操作 ");
            }
            if (date == null)
            {
                date = DateTime.Now;
            }
            var learnTrainMonthAnalysisDto = new LearnTrainAnalysisDto
            {
                LearnTrainLastMonthAnalysis = this.pendingLearningVehicleData.GetTrainSeheduleAnalysisAsync(admin.AgentRecord.AgentRecordId, date.Value.AddMonths(-1)).GetAwaiter().GetResult().As<IEnumerable<LearnTrainMonthAnalysisDto>>(),
                LearnTrainCurrentMonthAnalysis = this.pendingLearningVehicleData.GetTrainSeheduleAnalysisAsync(admin.AgentRecord.AgentRecordId, date.Value).GetAwaiter().GetResult().As<IEnumerable<LearnTrainMonthAnalysisDto>>()
            };
            return learnTrainMonthAnalysisDto;
        }

        /// <summary>
        /// 考试人数
        /// </summary>
        /// <param name="admin">管理员</param>
        /// <param name="datetime">时间</param>
        /// <returns></returns>
        public ExamineDriverCountDto QueryFirstExamDriverCount(AdminDto admin, DateTime? datetime)
        {
            if (admin.AgentRecord==null)
            {
                throw new ArgumentException(" 用户认证失败,错误操作 ");
            }
            var data = this.pendingLearningVehicleData.GetFirstExamDriverCount(admin.AgentRecord.AgentRecordId, datetime).GetAwaiter().GetResult();
            data.FirstExamDriverRate = Compare.GetRate(Convert.ToDecimal(data.FirstExamDriverCount), Convert.ToDecimal(data.AllExamDriverCount));//首次补考人数
            data.TwiceExamDriverRate = Compare.GetRate(Convert.ToDecimal(data.TwiceExamDriverCount), Convert.ToDecimal(data.AllExamDriverCount));//二次补考人数
            data.FirstPassDriverRate = Compare.GetRate(Convert.ToDecimal(data.FirstPassDriverCount), Convert.ToDecimal(data.AllExamDriverCount));//首次通过人数
            data.FirstMakeupPassDriverRate = Compare.GetRate(Convert.ToDecimal(data.FirstMakeupPassDriverCount), Convert.ToDecimal(data.AllExamDriverCount));//一次补考通过人数
            data.TwiceMakeupPassDriverRate = Compare.GetRate(Convert.ToDecimal(data.TwiceMakeupPassDriverCount), Convert.ToDecimal(data.AllExamDriverCount));//二次补考通过人数
            data.NotPassDriverRate = Compare.GetRate(Convert.ToDecimal(data.NotPassDriverCount), Convert.ToDecimal(data.AllExamDriverCount));//未通过人数
            return data.As<ExamineDriverCountDto>();
        }

        /// <summary>
        /// 累计培训人数统计
        /// </summary>
        /// <returns></returns>
        public TrainCountDto QueryTrainCountDetailList(AdminDto admin)
        {
            if (admin.AgentRecord == null)
            {
                throw new ArgumentException(" 用户验证失败,错误操作 ");
            }
            var endDate = DateTime.Now.Date;
            var startDate = DateTime.Now.Date.AddYears(-2);
            var count = endDate.Year * 12 + endDate.Month - startDate.Year * 12 - startDate.Month;
            var result = this.pendingLearningVehicleData.GetTrainCountDetailList(admin.AgentRecord.AgentRecordId).GetAwaiter().GetResult();
            TrainCountDto trainCount = new TrainCountDto
            {
                AllTrainCount = result.Sum(p => p.TrainCount),
                TrainDetaillist = new List<TrainDetailDto>()
            };
            var tempDate = startDate;
            for (int i = 0; i < count; i++)
            {
                var trainDetail = new TrainDetailDto
                {
                    TrianDate = tempDate.ToString("yyyy-MM")
                };
                if (result.Any(p => p.TrainDate == tempDate.ToString("yyyy-MM")))
                {
                    trainDetail.TrainCount = result.FirstOrDefault(p => p.TrainDate == tempDate.ToString("yyyy-MM")).TrainCount;
                }
                tempDate = tempDate.AddMonths(1);
                trainCount.TrainDetaillist.Add(trainDetail);
            }
            return trainCount;
        }

        #endregion


        public PageableList<LearnTrainHistoryRecordDto> GetLearnTrainHistoryRecord(AdminDto admin, string vehicleNo, long? trainingSiteConfigId,
            DateTime? trainingStartDate, DateTime? trainingEndDate, int pageIndex, int pageSize)
        {
            if (admin.AgentRecord == null)
            {
                throw new ArgumentException(" 员工认证失败,错误操作 ");
            }
            string cacheKey = this.redisService.GetKey(keyLearnTrainHistoryRecord, admin.AgentRecord.AgentRecordId, vehicleNo,
                    trainingSiteConfigId, trainingStartDate, trainingEndDate, pageIndex, pageSize);
            var resultRedis = this.redisService.TryGet(cacheKey, () =>
            {
                var (data, dataCount) = this.pendingLearningVehicleData.GetLearnTrainHistoryRecordEntity(admin.AgentRecord.AgentRecordId, vehicleNo,
                    trainingSiteConfigId, trainingStartDate, trainingEndDate, pageIndex, pageSize).GetAwaiter().GetResult();
                return new PageableList<LearnTrainHistoryRecordDto>
                {
                    Items = data.As<List<LearnTrainHistoryRecordDto>>(),
                    Count = dataCount,
                    PageIndex = pageIndex,
                    PageSize = pageSize,
                    ServerTime = DateTime.Now,
                };
            }, TimeSpan.FromDays(1));
            return resultRedis;
        }

    }
}